package net.bcxuexi.ports;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;

import net.bcxuexi.ports.model.IPort;
import net.bcxuexi.tools.MyLog;
import net.bcxuexi.tools.StringUtils; 

/**
 * 对ports.properties模板进行管理
 * 
 * @author mw
 */ 
public class LoadPorts {
	private static LoadPorts tplEngine;
	private final static String resourcesPath = "ports.properties";
	// properties 版本号，决定是否重新读取文件
	private String properVersion = "";
	// 服务器与客服端的通信端口
	private int serverPort = -1;
	private String serverIp = "";
	private String logFile = "client.log";
	//保存所有clientKey
	//private Set<String> clientKeys = new HashSet<String>();
	// 客户端需要映射的端口 List<IPort>
	private List<IPort> clientIPorts = new ArrayList<IPort>();
	// 更新clientIPorts之前，先把数据更新到cacheMap 在把cacheMap赋值给clientIPorts
	// 解决直接更新clientIPorts别人在读的问题
	private List<IPort> cacheMap = new ArrayList<IPort>();
	private String classesPath = LoadPorts.class.getClassLoader()
			.getResource("").getPath();

	private LoadPorts() {

	}

	private void init() {
		readTask.run();
		// 每10秒钟判断下是否需要重新加载文件
		Timer timer = new Timer();
		timer.schedule(readTask, 10000, 10000);

	}

	public int getServerPort() {
		return serverPort;
	}

	public void setServerPort(int serverPort) {
		this.serverPort = serverPort;
	}

	public String getServerIp() {
		return serverIp;
	}

	public void setServerIp(String serverIp) {
		this.serverIp = serverIp;
	}

	/**
	 * 得到所有端口
	 */
	public List<IPort> getAll() {
		return clientIPorts;
	}

	private TimerTask readTask = new TimerTask() {
		@Override
		public void run() {
			// 读取最新文件
			List<IPort> allMapTmp = new ArrayList<IPort>();
			Set<String> clientKeysTmp = new HashSet<String>();
			Properties prop = loadProperties();
			// 版本号是否发生变化
			String version = prop.getProperty("version");

			boolean reload = false;
			if (!properVersion.equals(version)) {
				reload = true;
			}
			properVersion = version;
			if (reload) {
				MyLog.info("更新配置文件");
				serverIp = prop.getProperty("server_ip");
				serverPort = Integer.valueOf(prop.getProperty("server_port"));
				logFile = prop.getProperty("log_file");
				Set<Object> keys = prop.keySet();
				for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
					String key = (String) iterator.next();
					String value = prop.getProperty(key);
					if (key.equals("version")) {
						continue;
					}else if(key.equals("server_ip")){
						continue;
					} else if (key.equals("server_port")) {
						continue;
					}else if(key.equals("log_file")){
						continue;
					}else if (key.contains("_port")
							&& key.startsWith("client")) {
						try {
							String sIPort[] = value.split(":");
							if (sIPort.length != 4) {
								MyLog.info("配置无效" + value);
								continue;
							}

							String clientKey = sIPort[0];
							int proxy = Integer.valueOf(sIPort[1]);
							String innerIp = sIPort[2];
							int innerPort = Integer.valueOf(sIPort[3]);
							clientKeysTmp.add(clientKey);
							IPort iPort = new IPort(clientKey,proxy, innerIp, innerPort, serverIp, serverPort);
							allMapTmp.add(iPort);
						} catch (Exception e) {
							MyLog.info("配置无效" + value);
							e.printStackTrace();
							continue;
						}
					}

				}
				// 更换
				cacheMap = new ArrayList<IPort>();
				cacheMap.addAll(allMapTmp);
				clientIPorts = cacheMap;
				//clientKeys = clientKeysTmp;
			}

		}
	};

	private Properties loadProperties() {
		Properties props = new Properties();
		InputStream is = null;
		try {
			is = new FileInputStream(new File(classesPath
					+ resourcesPath));
			props.load(is);
		} catch (IOException ex) {
			MyLog.info("Could not load properties from path:" + resourcesPath
					+ ", " + ex.getMessage());
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return props;
	}

	public boolean hasClientKey(String clientKey){
		for (Iterator iterator = clientIPorts.iterator(); iterator.hasNext();) {
			IPort iport = (IPort) iterator.next();
			if(!StringUtils.isBlack(clientKey)&&clientKey.equals(iport.getClientKey())){
				return true;
			}
		}
		return false;
	}

	public String getLogFile() {
		return logFile;
	}

	public static synchronized LoadPorts getInstance() {
		if (tplEngine == null) {
			tplEngine = new LoadPorts();
			tplEngine.init();
		}
		return tplEngine;
	}
}
